
#include<iostream>
#include<string.h>
#include<strings.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<sys/types.h>
#include <arpa/inet.h>
#include <mutex>

#include"Inetaddr.hpp"
#include"Log.hpp"

std::mutex cout_mutex; // 保护 cout 的互斥锁
//#include"Mutex.hpp"

using namespace MutexMod;
using namespace LogMod;

int _sfd; 


void* Send(void* argv)
{
    Inetaddr* addr = static_cast<Inetaddr*>(argv);
    while(1)
    {
        std::string strsay;
        {
            std::lock_guard<std::mutex> lock(cout_mutex);
            std::cout<<"please say# ";
        }
        std::getline(std::cin,strsay);
        ssize_t sz = sendto(_sfd,strsay.c_str(),strsay.size(),0,(struct sockaddr*)&addr->Getaddr(),sizeof(addr->Getaddr()));
        if(sz < 0)
        {
            LOG(level::ERROR)<<"send false";
            exit(1);
        }
    }
}

void* Recv(void* argv)
{
    while(1)
    {
        char buff[512];
        struct sockaddr_in revaddr;
        bzero(&revaddr,0);
        socklen_t revsize = sizeof(revaddr);
        ssize_t n = recvfrom(_sfd,buff,sizeof(buff),0,(struct sockaddr*)&revaddr,&revsize);
        Inetaddr revInet(revaddr); 
        if(n > 0)
        {
            buff[n] = 0;
            std::string message = "[ " + revInet.String_addr() + "] say# " + buff;
            std::lock_guard<std::mutex> lock(cout_mutex);
            std::cout<<message<<std::endl;
        }
    }
    


}

int main(int argc,char * argv[])
{
    if(argc != 3)
    {
        LOG(level::ERROR)<<"you should"<<argv[0]<<" ip port";
        return 1;
    }
    int port = std::stoi(argv[2]);
    char* ip = argv[1];
    std::cout<<"main: "<<port<<std::endl;
    _sfd = socket(AF_INET,SOCK_DGRAM,0);

    // struct sockaddr_in addr;
    // bzero(&addr,0);
    // addr.sin_family = AF_INET;
    // addr.sin_port = htons(port);
    // addr.sin_addr.s_addr = inet_addr(ip);
    Inetaddr addr(ip,port);

    //  while(1)
    // {
    //     std::string strsay;
    //     std::cout<<"please say# ";
    //     std::getline(std::cin,strsay);
    //     ssize_t sz = sendto(_sfd,strsay.c_str(),strsay.size(),0,(struct sockaddr*)&addr.Getaddr(),sizeof(addr.Getaddr()));
    //     if(sz < 0)
    //     {
    //         LOG(level::ERROR)<<"send false";
    //         exit(1);
    //     }

    //     // struct sockaddr_in addr;
    //     // bzero(&addr,0);
    //     // addr.sin_family = AF_INET;
    //     // addr.sin_port = htons(port);
    //     // // addr.sin_addr.s_addr = inet_addr(ip);
    //     // inet_pton(AF_INET,ip,&addr.sin_addr);
    //     // socklen_t size = sizeof(addr);
    //     // std::string strsay;
    //     // std::cout<<"please say# ";
    //     // std::getline(std::cin,strsay);
    //     // ssize_t sz = sendto(_sfd,strsay.c_str(),strsay.size(),0,(struct sockaddr*)&addr,size);

    // }

    //Send();
    // pthread_t send,recv;
    // pthread_create(&send,NULL,Send,(void*)&addr);
    // pthread_create(&recv,NULL,Recv,nullptr);

    // pthread_join(send,NULL);
    // pthread_join(recv,NULL);


     while(1)
    {
        struct sockaddr_in addr;
        bzero(&addr,0);
        addr.sin_family = AF_INET;
        addr.sin_port = htons(port);
        addr.sin_addr.s_addr = inet_addr(ip);
        socklen_t size = sizeof(addr);
        std::string strsay;
        std::cout<<"please say# ";
        //getline(strsay,sizeof(strsay),stdin);
        std::getline(std::cin,strsay);
        ssize_t sz = sendto(_sfd,strsay.c_str(),strsay.size(),0,(struct sockaddr*)&addr,size);
        char buff[512];
        struct sockaddr_in revaddr;
        bzero(&revaddr,0);
        socklen_t revsize = sizeof(revaddr);
        ssize_t n = recvfrom(_sfd,buff,sizeof(buff),0,(struct sockaddr*)&revaddr,&revsize);
        Inetaddr tmpaddr(revaddr);
        if(n > 0)
        {
            buff[n] = 0;
            std::string myecho = tmpaddr.String_addr() + "say# "+buff;
            std::cout<<myecho<<std::endl;
        }
    }


    return 0;
}